package com.jade.bss.admin.role.impl;

import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.bss.admin.AdminException;
import com.jade.bss.admin.role.PrincipalRole;
import com.jade.bss.admin.role.RoleDao;
import com.jade.bss.admin.role.RoleEntry;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 采用JPA方式实现的角色数据访问接口。
 *
 * @author sky
 * @version 1.0 13-4-18 上午9:57
 */
@Named ("bss_roleDao")
public class JpaRoleDao implements RoleDao
{
    @PersistenceContext (unitName = "default")
    protected EntityManager em;

    @Caching (evict = {@CacheEvict (value = "bss.role.gn", key = "#role.name"),
                       @CacheEvict (value = "bss.role.la", allEntries = true),
                       @CacheEvict (value = "bss.role.q", allEntries = true),
                       @CacheEvict (value = "bss.role.g", key = "#role.id"),
                       @CacheEvict (value = "bss.role.lt", key = "#role.type")})
    public int addRole(RoleEntry role)
            throws AdminException
    {
        em.persist(role);
        return role.getId();
    }

    @Caching (evict = {@CacheEvict (value = "bss.role.gn", key = "#role.name"),
                       @CacheEvict (value = "bss.role.la", allEntries = true),
                       @CacheEvict (value = "bss.role.q", allEntries = true),
                       @CacheEvict (value = "bss.role.g", key = "#role.id"),
                       @CacheEvict (value = "bss.role.lt", key = "#role.type")})
    public void removeRole(RoleEntry role)
            throws AdminException
    {
        em.remove(getRole(role.getId()));
    }

    @Caching (evict = {@CacheEvict (value = "bss.role.gn", key = "#role.name"),
                       @CacheEvict (value = "bss.role.la", allEntries = true),
                       @CacheEvict (value = "bss.role.q", allEntries = true),
                       @CacheEvict (value = "bss.role.g", key = "#role.id"),
                       @CacheEvict (value = "bss.role.lt", key = "#role.type")})
    public void updateRole(RoleEntry role)
            throws AdminException
    {
        em.merge(role);
    }

    @Cacheable (value = "bss.role.g", key = "#id")
    public RoleEntry getRole(int id)
    {
        return em.find(RoleEntry.class, id);
    }

    @Cacheable (value = "bss.role.gn", key = "#name")
    public RoleEntry getRole(String name)
    {
        String sql = "SELECT role FROM RoleEntry role WHERE name=:name";
        Query query = em.createQuery(sql);
        query.setParameter("name", name);
        List result = query.getResultList();
        if (result == null || result.size() == 0) {
            return null;
        }
        return (RoleEntry)result.get(0);
    }

    @Cacheable (value = "bss.role.la", key = "'all'")
    @SuppressWarnings (value = "unchecked")
    public List<RoleEntry> listRole()
    {
        String sql = "SELECT role FROM RoleEntry role ORDER BY creationDate DESC";
        Query query = em.createQuery(sql);
        return query.getResultList();
    }

    @Cacheable (value = "bss.role.lt", key = "#type")
    public List<RoleEntry> listRole(String type)
    {
        String sql = "SELECT role FROM RoleEntry role WHERE type=:type";
        Query query = em.createQuery(sql);
        query.setParameter("type", type);
        return query.getResultList();
    }

    @Cacheable (value = "bss.role.q", key = "#criteria.toString()")
    public PagingList<RoleEntry> queryRole(Criteria criteria)
    {
        String sql = "SELECT role FROM RoleEntry role";
        return SqlUtils.sqlQuery(sql, em, criteria);
    }

    @Caching (evict = {@CacheEvict (value = "bss.role.gn", allEntries = true),
                       @CacheEvict (value = "bss.role.la", allEntries = true),
                       @CacheEvict (value = "bss.role.q", allEntries = true),
                       @CacheEvict (value = "bss.role.g", key = "#id"),
                       @CacheEvict (value = "bss.role.lt", allEntries = true)})
    public void updateStatus(int id, int status)
            throws AdminException
    {
        String sql = "UPDATE RoleEntry SET status=:status WHERE id=:id";
        Query query = em.createQuery(sql);
        query.setParameter("id", id);
        query.setParameter("status", status);
        query.executeUpdate();
    }

//    @Cacheable (value = "bss.role.lpr", key = "#principalType + #principalName")
    //    @SuppressWarnings (value = "unchecked")
    //    public List<PrincipalRole> listPrincipalRole(String principalType, String principalName)
    //    {
    //        String sql = "SELECT pr FROM PrincipalRole pr WHERE principalType=:principalType AND " +
    //                     "principalName=:principalName";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("principalType", principalType);
    //        query.setParameter("principalName", principalName);
    //        return query.getResultList();
    //    }
    //
    //    @Cacheable (value = "bss.role.lpr2", key = "#roleId")
    //    @SuppressWarnings (value = "unchecked")
    //    public List<PrincipalRole> listPrincipalRole(int roleId)
    //    {
    //        String sql = "SELECT pr FROM PrincipalRole pr WHERE role.id=:roleId";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("roleId", roleId);
    //        return query.getResultList();
    //    }
    //
    //    @Cacheable (value = "bss.role.gpr", key = "#principalType + #principalName + #roleId")
    //    @SuppressWarnings (value = "unchecked")
    //    public PrincipalRole getPrincipalRole(String principalType, String principalName, int roleId)
    //    {
    //        String sql = "SELECT pr FROM PrincipalRole pr WHERE principalType=:principalType AND " +
    //                     "principalName=:principalName AND role.id=:roleId";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("principalType", principalType);
    //        query.setParameter("principalName", principalName);
    //        query.setParameter("roleId", roleId);
    //        return SqlUtils.getSingleResult(query);
    //    }
    //
    //    @Caching (evict = {@CacheEvict (value = "bss.role.lpr2", allEntries = true),
    //                       @CacheEvict (value = "bss.role.gpr", key = "#pr.principalType + #pr.principalName + #pr.role.id"),
    //                       @CacheEvict (value = "bss.role.lpr", key = "#pr.principalType + #pr.principalName")})
    //    public void addPrincipalRole(PrincipalRole pr)
    //    {
    //        em.persist(pr);
    //    }
    //
    //    @Caching (evict = {@CacheEvict (value = "bss.role.lpr2", allEntries = true),
    //                       @CacheEvict (value = "bss.role.gpr", allEntries = true),
    //                       @CacheEvict (value = "bss.role.lpr", key = "#principalType + #principalName")})
    //    public void removePrincipalRole(String principalType, String principalName)
    //    {
    //        String sql = "DELETE FROM PrincipalRole WHERE principalType=:principalType AND principalName=:principalName";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("principalType", principalType);
    //        query.setParameter("principalName", principalName);
    //        query.executeUpdate();
    //    }
    //
    //    @Caching (evict = {@CacheEvict (value = "bss.role.lpr2", key = "#roleId"),
    //                       @CacheEvict (value = "bss.role.gpr", allEntries = true),
    //                       @CacheEvict (value = "bss.role.lpr", allEntries = true)})
    //    public void removePrincipalRole(int roleId)
    //    {
    //        String sql = "DELETE FROM PrincipalRole WHERE role.id=:roleId";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("roleId", roleId);
    //        query.executeUpdate();
    //    }
    //
    //    @Caching (evict = {@CacheEvict (value = "bss.role.lpr2", key = "#roleId"),
    //                       @CacheEvict (value = "bss.role.gpr", key = "#principalType + #principalName + #roleId"),
    //                       @CacheEvict (value = "bss.role.lpr", key = "#principalType + #principalName")})
    //    public void removePrincipalRole(String principalType, String principalName, int roleId)
    //    {
    //        String sql = "DELETE FROM PrincipalRole WHERE principalType=:principalType AND " +
    //                     "principalName=:principalName AND role.id=:roleId";
    //        Query query = em.createQuery(sql);
    //        query.setParameter("principalType", principalType);
    //        query.setParameter("principalName", principalName);
    //        query.setParameter("roleId", roleId);
    //        query.executeUpdate();
    //    }
}
